
from PyQt5.QtCore import *
from PyQt5.QtWidgets import *

class CKeypadDisplay:
    
    def __init__(self,  infoWidget, valueWidget):
        
        self.infoWidget = infoWidget
        self.valueWidget = valueWidget
        self.valueString = ''
        self.caret = -1
        self.flashOn = False

                
    def WriteInfo(self, content):
        self.infoWidget.setText(content)
        
    def WriteValue(self, value):
        self.valueString = value
        self.valueWidget.setText(value)
        
#    def MoveCaretLeft(self,  max):
#        self.caret = self.caret + 1
#        if self.valueString[self.caret] == '.':
#            self.caret = self.caret + 1
#            
#    def MoveCaretRight(self, max):
#        self.caret = self.caret - 1
#        if self.valueString[self.caret] == '.':
#            self.caret = self.caret - 1
#        
#    def DisableCaret(self):
#        self.caret = -1
#        
#    def UpdateCaret(self):
#        self.flashOn = not self.flashOn
#        
#        if not self.flashOn:
#            self.valueWidget.setText(self.valueString[0:self.caret] + '_' + \
#                                                self.valueString[self.caret+1:len(self.valueString)])
#        else:
#            self.valueWidget.setText(self.valueString)
            
        

class CKeypadComm:
    
    def __init__(self,  port):
        self.port = port
        self.maxMenu = 15
        self.maxParam = 20
        self.activeParamInMenu = [0 for i in range(0, self.maxMenu + 1)]
        self.activeMenu = 0
        self.paramList = []
        self.state = 0
        self.readyState = 0
        self.runState = 1
        self.tripState = 2
        
        for menu in range(0, self.maxMenu + 1):
            params = []
            for param in range(0, self.maxParam + 1):
                params.append(menu*1000 + param)
                
            self.paramList.append(params)
                
        
    def GetNextMenu(self, menu):
        
        menu = menu + 1
        if menu > self.maxMenu:
            menu = 0
            
        self.activeMenu = menu
        param = self.activeParamInMenu[menu]
        return [menu, param, self.paramList[menu][param], -32768, 32767,  0, 0, 0]
        
    def GetPrevMenu(self, menu):
        
        menu = menu - 1
        if menu < 0:
            menu = self.maxMenu
            
        self.activeMenu = menu
        param = self.activeParamInMenu[menu]
            
        return [menu, param, self.paramList[menu][param], -32768, 32767,  0, 0, 0]
        
    def GetNextParam(self, menu,  param):
        param = param + 1
        
        if param > self.maxParam:
            param = int(0)
            
        self.activeMenu = menu
        self.activeParamInMenu[menu] = param
        return [menu, param, self.paramList[menu][param], -32768, 32767,  0, 0, 0]
        
    def GetPrevParam(self, menu,  param):
        param = param - 1
        
        if param < 0:
            param = self.maxParam
            
        self.activeMenu = menu
        self.activeParamInMenu[menu] = param
        return [menu, param, self.paramList[menu][param], -32768, 32767,  0, 0, 0]
        
    def GetactiveParam(self):
        menu = self.activeMenu
        param = self.activeParamInMenu[menu]
        return [menu, param, self.paramList[menu][param], -32768, 32767,  0, 0, 0]
        
        
    def WriteAcitvePar(self, value):
        activeParam = self.activeParamInMenu[self.activeMenu]
        self.paramList[self.activeMenu][activeParam] = value
        
    def RequestToState(self, newState):
        return newState
        
    def GetDeviceState(self):
        return self.state
        
    def Run(self):
        self.state = self.runState
        
    def Stop(self):
        self.state = self.readyState

class CKeypad:
    
    def __init__(self,  display,  targetDevice):
        
        self.display = display
        self.device = targetDevice
        
        self.statusState = 0
        self.paramViewState = 1
        self.paramEditState = 2
        self.messageState = 3
        
        self.state = self.statusState
        
        self.memMode = False
        self.active = False
        
        self.activeMenu = 0
        self.activeParam = 0
        self.activeValue = 0
        self.activeUnit = 0
        self.activeFormat = 0
        self.activeMin = 0
        self.activeMax = 100
        self.activeMessaage = ''
        
        self.driveState = 0
        self.driveStateReady = 0
        self.driveStateRun = 1
        self.driveStateTrip = 2
        self.stateString = ['Ready', 'Run', 'Trip']
        self.unitString = ['', 'Hz', 'V','A']
        
        self.caretPos = -1
        self.displayCaret = -1
        
        self.prIndexMenu = 0
        self.prIndexParam = 1
        self.prIndexValue = 2
        self.prIndexMin = 3
        self.prIndexMax = 4
        self.prIndexDefault = 5
        self.prIndexUnit = 6
        self.prIndexDF = 7
        
        self.flashOn = False
        self.count = 0
        
    def SetActive(self, newState):
        self.active = newState
        
        
    def UpdateDisplay(self):
        
        self.count = self.count + 1
        if self.count > 5:
            self.flashOn  = not self.flashOn
            self.count = 0
        
        if self.state == self.statusState or self.state == self.messageState:
            self.driveState = self.GetDeviceState()
            self.display.WriteInfo(self.stateString[self.driveState])
        elif self.state == self.paramViewState or self.state == self.paramEditState:
            if self.state == self.paramViewState:
                self.GetactiveParam()
            self.display.WriteInfo('F%02d.%03d'%(self.activeMenu, self.activeParam))
            
        self.display.WriteValue(self.GetActiveValueString())
            
    def GetActiveValueString(self):
        
        s = ''
        
        if self.state == self.paramEditState and not self.flashOn:
            s = '% 10d'%self.activeValue
            l = list(s)
            if l[len(l) - self.caretPos - 1] == ' ':
                l[len(l) - self.caretPos - 1] = '_'
            else:
                l[len(l) - self.caretPos - 1] = ' '
            s = ''.join(l) + self.unitString[self.activeUnit]
         
        else:
            s = '% 10d%s'%(self.activeValue, self.unitString[self.activeUnit])
            
        return s
            
    def EnterAction(self):
        
        if self.state == self.statusState:
            self.RequestToState(self.paramViewState)
        elif self.state == self.paramViewState:
            self.RequestToState(self.paramEditState)
        elif self.state == self.paramEditState:
            self.AcceptValue()
            self.RequestToState(self.paramViewState)
            
            
    def EscAction(self):
        
        if self.state == self.paramEditState :
            self.RequestToState(self.paramViewState)
        elif self.state == self.paramViewState:
            self.RequestToState(self.statusState)  
        
        
    def LeftAction(self):
        
        if self.state == self.paramViewState:
            
            self.GetNextMenu(self.activeMenu)
                
            
        elif self.state == self.paramEditState:
                            
            self.caretPos = self.caretPos + 1
            if self.caretPos == 10:
                self.caretPos = 0
                
        elif self.state == self.statusState:
            self.RequestToState(self.paramViewState)
                
    def RightAction(self):
        
        if self.state == self.paramViewState:
            
            self.GetPrevMenu(self.activeMenu)
        
        elif self.state == self.paramEditState:
            
            self.caretPos = self.caretPos - 1
            if self.caretPos == -1:
                self.caretPos = 10
                
        elif self.state == self.statusState:
            self.RequestToState(self.paramViewState)
        
                
    def UpAction(self):
        
        if self.state == self.paramViewState:
            
            self.device.GetNextParam(self.activeMenu, self.activeParam)
         
        elif self.state == self.paramEditState: 
            
            self.activeValue = self.activeValue + 10**self.caretPos
            
            if self.activeValue > self.activeMax:
                self.activeValue = self.activeMax
            
        elif self.state == self.statusState:
            self.RequestToState(self.paramViewState)

    def DownAction(self):
        
        if self.state == self.paramViewState:
            
            self.GetPrevParam(self.activeMenu, self.activeParam)
         
        elif self.state == self.paramEditState: 
            
            self.activeValue = self.activeValue - 10**self.caretPos
            
            if self.activeValue > self.activeMax:
                self.activeValue = self.activeMax
            
        elif self.state == self.statusState:
            self.RequestToState(self.paramViewState)
 
    def RunAction(self):
        self.device.Run()
        
    def StopAction(self):
        self.device.Stop()
        
    def RequestToState(self, newState):
        self.state = self.device.RequestToState(newState)
        if self.state != self.paramEditState:
            self.caretPos = -1
            self.displayCaret = -1
        else:
            self.caretPos = 0
            self.displayCaret = 0
            
        
    def AcceptValue(self):
        
        self.device.WriteAcitvePar(self.activeValue)
        
    def GetNextMenu(self, menu):
        paramResponse = self.device.GetNextMenu(menu)
        self.ParseParamResponse(paramResponse)
        
    def GetPrevMenu(self, menu):
        paramResponse = self.device.GetPrevMenu(menu)
        self.ParseParamResponse(paramResponse)
        
    def GetNextParam(self, menu, param):
        if param < 0:
            param = int(0)
        paramResponse = self.device.GetNextParam(menu, param)
        self.ParseParamResponse(paramResponse)
        
    def GetPrevParam(self, menu, param):
        if param < 0:
            param = int(0)
        paramResponse = self.device.GetPrevParam(menu, param)
        self.ParseParamResponse(paramResponse)
        
    def GetactiveParam(self):
        paramResponse = self.device.GetactiveParam()
        self.ParseParamResponse(paramResponse)
        
        
    def ParseParamResponse(self, paramResponse):   
        self.activeMenu = paramResponse[self.prIndexMenu]
        self.activeParam = paramResponse[self.prIndexParam]
        self.activeValue = paramResponse[self.prIndexValue]
        self.activeMin = paramResponse[self.prIndexMin]
        self.activeMax = paramResponse[self.prIndexMax]
        self.activeDefault = paramResponse[self.prIndexDefault]
        self.activeUnit = paramResponse[self.prIndexUnit]
        self.activeFormat = paramResponse[self.prIndexDF]
         
     
    def GetDeviceState(self):
        return self.device.GetDeviceState()
        
    
